﻿using System;
using System.Collections.Generic;
using System.Text;
using Slaks.DocumentSerialization.Document.Wordnet;
using Slaks.DocumentSerialization.TermIdInfo;
using Wnlib;
using PartOfSpeech = Slaks.DocumentSerialization.Document.Wordnet.PartOfSpeech;
using Synonym = Slaks.DocumentSerialization.Document.Wordnet.Synonym;

namespace TextParsing.Stemmers
{
    class WordnetStemmer:IStemmer
    {
        private static Opt _synonymsOpt = null;
        static WordnetStemmer()
        {
            Opt opt;

            Wnlib.PartOfSpeech pos = Wnlib.PartOfSpeech.of("noun");

            for (int i = 0; i < Opt.Count; i++)
            {
                opt = Opt.at(i);
                if (opt.pos == pos)
                {
                    if (opt.label == "Synonyms/Hypernyms (Ordered by Estimated Frequency): brief")
                    {
                        _synonymsOpt = opt;
                        break;
                    }
                }
            }
        }
        private string MakeBasicAdditionalStemming(string term, ref Wnlib.PartsOfSpeech pos)
        {
            if (term.Length <= 3) return null;

            string newTerm = term;

            int termLength = term.Length;
            WnLexicon.WordInfo wordinfo = null;
            if (term[termLength - 2] == 'e' && term[termLength - 1] == 'd')
            {
                newTerm = term.Substring(0, termLength - 2);
                wordinfo = WnLexicon.Lexicon.FindWordInfo(newTerm, true);
                pos = wordinfo.partOfSpeech;
                if (wordinfo.partOfSpeech == Wnlib.PartsOfSpeech.Unknown)
                {
                    newTerm += 'e';
                    wordinfo = WnLexicon.Lexicon.FindWordInfo(newTerm, true);
                    pos = wordinfo.partOfSpeech;
                    if (wordinfo.partOfSpeech == Wnlib.PartsOfSpeech.Unknown) return null;
                }
            }
            else if (term[termLength - 3] == 'i' && term[termLength - 2] == 'n' && term[termLength - 1] == 'g')
            {
                newTerm = term.Substring(0, termLength - 3);
                wordinfo = WnLexicon.Lexicon.FindWordInfo(newTerm, true);
                pos = wordinfo.partOfSpeech;
                if (wordinfo.partOfSpeech == Wnlib.PartsOfSpeech.Unknown) return null;
            }
            else if (term[termLength - 1] == 's')
            {
                newTerm = term.Substring(0, termLength - 1);
                wordinfo = WnLexicon.Lexicon.FindWordInfo(newTerm, true);
                pos = wordinfo.partOfSpeech;
                if (wordinfo.partOfSpeech == Wnlib.PartsOfSpeech.Unknown) return null;
            }

            return newTerm;
        }

        //private void FindSynonyms(WordnetNode node, ref long idCounter)
        //{


        //    Wnlib.Search search = new Wnlib.Search(node.Term, true, _synonymsOpt.pos, _synonymsOpt.sch, 0);

        //    if (search.senses == null) return;
        //    foreach (SynSet senses in search.senses)
        //    {
        //        foreach (Lexeme word in senses.words)
        //        {
        //            Synonym syn = new Synonym(node.Id, node);
        //            if (word.word != node.Term) this.AddSynonym(word.word, syn, ref idCounter); //root of the synonyms
        //            if (senses.senses == null)
        //            {
        //                if (syn.SynonymIdList().Count > 0) node.SynonymList.Add(syn);
        //                continue;
        //            }
        //            foreach (SynSet senses2 in senses.senses)
        //            {
        //                foreach (Lexeme word2 in senses2.words) //synonyms of the one of the categories
        //                {
        //                    if (word2.word != node.Term) this.AddSynonym(word2.word, syn, ref idCounter);
        //                }
        //            }

        //            if (syn.SynonymIdList().Count > 0) node.SynonymList.Add(syn);
        //        }
        //    }

        //}
        //private void AddSynonym(string term, Synonym synonym, ref long idCounter)
        //{
        //    if (term.Length <= 2) return;
        //    if (term.IndexOf("_") >= 0) return;
        //    if (term.IndexOf("-") >= 0) return;
        //    term = term.ToLower();

        //    TermIdInfoElement termIdInfoElement = (m_term2id.Contains(term) == true) ? m_term2id[term] : null;

        //    if (termIdInfoElement == null) //this term not present in the hash
        //    {
        //        ++idCounter;
        //        termIdInfoElement = new TermIdInfoElement(term, idCounter, 0);
        //        m_term2id.Add(term, termIdInfoElement);
        //        synonym.AddSynonymId(idCounter);
        //    }
        //    else
        //    {
        //        long id = termIdInfoElement.Id;
        //        synonym.AddSynonymId(id);
        //    }
        //}

        public string StemTerm(string term)
        {
            WnLexicon.WordInfo wordinfo = WnLexicon.Lexicon.FindWordInfo( term, true );
            if (wordinfo.partOfSpeech == Wnlib.PartsOfSpeech.Unknown) return string.Empty;
            if (wordinfo.text != String.Empty) term = wordinfo.text;
            return MakeBasicAdditionalStemming(term, ref wordinfo.partOfSpeech);
        }
    }
}
